package org.lora.core.bean.impl;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import javax.sql.DataSource;

import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;

import org.apache.dataconn.jdbc.pool.PoolConfiguration;
import org.apache.dataconn.jdbc.pool.PoolProperties;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.log4j.Logger;
import org.lora.core.annotation.Action;
import org.lora.core.annotation.AutoAssemble;
import org.lora.core.annotation.Service;
import org.lora.core.bean.ILoraBeanFactory;
import org.lora.core.bean.ProxyMethodInterceptor;
import org.lora.core.configxml.entity.ConfigXmlEntity;
import org.lora.core.configxml.entity.MongoDBConfig;
import org.lora.core.configxml.entity.MyBatisConfig;
import org.lora.core.configxml.entity.WebSecurityConfig;
import org.lora.core.context.WebContext;
import org.lora.core.jdbctx.impl.MapperTransactionFactoryImpl;
import org.lora.core.mongodb.IMongoDAO;
import org.lora.core.mongodb.impl.MongoDAOImpl;
import org.lora.core.mybatis.Dialect;
import org.lora.exception.LoraCoreException;
import org.lora.exception.handle.ErrorContext;
import org.lora.exception.handle.ExceptionPackageFactory;
import org.lora.log4j.Log4jUtil;
import org.lora.mvc.security.ISecurityService;
import org.lora.mvc.security.context.SecurityContext;
import org.lora.util.ReflectUtil;
import org.lora.util.StringUtil;
import org.lora.util.ValidateUtil;

import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.ServerAddress;

/**
 * <p>
 * Title:LoraBeanFactoryImpl
 * </p>
 * <p>
 * Desription:Bean装配工厂 所有被lora框架管控的类，都在这个工厂中创建出来。
 * </p>
 * Create Time:2016年7月6日 下午1:23:53
 * 
 * @author Bladnir@outlook.com
 *         <p>
 *         History:
 *         </p>
 *         2016年07月06日 Bladnir Create<br>
 *         2016年07月07日 Bladnir 修改装配方法，解决Service重复装配问题<br>
 *         2016年07月11日 Bladnir 重新封装JDK的异常，提示更人性化<br>
 *         2016年07月30日 Bladnir 加入SecurityContext的封装<br>
 *         2016年09月21日 Bladnir 遇到无法装配的对象时候不再抛错 而是忽略到这个 继续装配<br>
 *         2016年11月04日 Bladnir 修改BoneCP配置 DisableConnectionTracking为true<br>
 *         2016年11月08日 Bladnir 装配数据源到WebContext key为EnvironmentName<br>
 *         为了方便以后可以直接监控连接池一侧的状态和接入Quartz框架使用<br>
 *         2016年11月10日 Bladnir 弃用BoneCP 改用 Tomcat JDBC<br>
 *         2016年11月14日 Bladnir 修改sqlSession的创建方式<br>
 *         之前的创建方式是线程不安全的，高并发下会造成连接释放问题<br>
 *         2016年11月16日 Bladnir 修改lora.xml配置的结构，所以修改数据源和mybatis初始化方法<br>
 *         2016年11月17日 Bladnir 修改事务部分代码 解决线程安全问题（表现问题为数据库连接不释放）<br>
 *         2016年12月02日 Bladnir 事务部分代码全部重构 解决线程安全问题（表现问题为数据库连接被不正确的关闭）<br>
 */
public class LoraBeanFactoryImpl implements ILoraBeanFactory {

	private ConfigXmlEntity configXmlEntity = null;

	private List<Class<?>> classList = new ArrayList<>();

	private TransactionFactory mapperTransactionFactory = new MapperTransactionFactoryImpl();

	private static final String CLASS_PATH = LoraBeanFactoryImpl.class.getClassLoader().getResource(StringUtil.BLANK).getPath();

	private static final String EXT = ".class";

	private static final String PROTOCOL_FILE = "file";

	private static final String PROTOCOL_JAR = "jar";

	private Logger systemLog = Log4jUtil.getSystemLogger();

	/**
	 * BoneCP 数据源Map key：environmentName
	 */
	private Map<String, DataSource> dataSourceMap = new HashMap<>();

	/**
	 * key:dao注解类的全名
	 */
	private Map<String, SqlSession> sqlSessionMap = new HashMap<>();

	/**
	 * key:dao注解类的全名
	 */
	private Map<String, SqlSessionFactory> sqlSessionFactoryMap = new HashMap<>();

	/**
	 * dao注解类的全名 的List 每个注解对应一个数据源
	 */
	private List<String> annotationClassNameList = new ArrayList<>();

	/**
	 * key:service接口类全名 value:装配好的实现对象
	 */
	private Map<String, Object> serviceBeanMap = new HashMap<>();

	/**
	 * 装配好的DAO实现 MongoClient就是这个实例的mongoClient
	 */
	private MongoDAOImpl mongoDAOImpl;

	/**
	 * 整个项目只有这一个MongoClient实例
	 */
	private MongoClient mongoClient;

	/**
	 * 构造方法
	 * 
	 * @param configXmlEntity
	 */
	public LoraBeanFactoryImpl(ConfigXmlEntity configXmlEntity) {
		this.configXmlEntity = configXmlEntity;
	}

	/**
	 * 创建数据源对象
	 * 
	 * @param poolName
	 * @param dataSourceConfigMap
	 * @return
	 * @throws LoraCoreException
	 * @throws NoSuchFieldException
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 */
	private javax.sql.DataSource createTomcatJDBCDataSource(String poolName, Map<String, Object> dataSourceConfigMap)
			throws LoraCoreException, NoSuchFieldException, IllegalAccessException, InstantiationException {

		String driverClassName = StringUtil.getStringFromMap("driverClassName", dataSourceConfigMap);
		ValidateUtil.isNull(driverClassName, "driverClassName");

		try {
			Class.forName(driverClassName);
		} catch (ClassNotFoundException e) {
			ErrorContext ec = new ErrorContext();
			ec.className(driverClassName).message(ErrorContext.CANT_FIND_CLASS);
			ExceptionPackageFactory.excute(e, ec);
		}

		PoolConfiguration poolProperties = ReflectUtil.reflectSimpleBean(PoolProperties.class, dataSourceConfigMap);
		poolProperties.setName(poolName);

		org.apache.dataconn.jdbc.pool.DataSource dataSource = new org.apache.dataconn.jdbc.pool.DataSource(poolProperties);

		dataSourceMap.put(poolName, dataSource);

		return dataSource;

	}

	/**
	 * 初始化数据源Map
	 * 
	 * @throws LoraCoreException
	 * @throws NoSuchFieldException
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 */
	private void initDataSource() throws LoraCoreException, NoSuchFieldException, IllegalAccessException, InstantiationException {

		Map<String, Map<String, Object>> dataSourceConfigMap = configXmlEntity.getDataSourceConfigMap();

		for (Entry<String, Map<String, Object>> entry : dataSourceConfigMap.entrySet()) {

			// 创建数据源对象
			createTomcatJDBCDataSource(entry.getKey(), entry.getValue());
		}
	}

	/**
	 * 初始化 和 MyBatis相关的配置<br>
	 * 初始化 sqlSessionMap<br>
	 * 
	 * @throws LoraCoreException
	 */
	@SuppressWarnings("unchecked")
	private void initMyBatisDAO() throws LoraCoreException {

		SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

		List<MyBatisConfig> myBatisConfigList = configXmlEntity.getMyBatisConfigList();

		for (MyBatisConfig config : myBatisConfigList) {

			String annotationClassName = config.getAnnotationClassName();
			annotationClassNameList.add(annotationClassName);

			Class<Annotation> daoAnnotationClass = null;
			try {
				// 后面要根据这个Class获取注解实例 所以这里只能强转
				daoAnnotationClass = (Class<Annotation>) Class.forName(annotationClassName);
			} catch (ClassNotFoundException e1) {
				ErrorContext ec = new ErrorContext();
				ec.className(annotationClassName).message(ErrorContext.CANT_FIND_CLASS);
				ExceptionPackageFactory.excute(e1, ec);
			}

			String dataSourceName = config.getDataSource();

			javax.sql.DataSource dataSource = dataSourceMap.get(dataSourceName);

			Environment environment = new Environment(config.getEnvironmentName(), mapperTransactionFactory, dataSource);
			Configuration configuration = new Configuration(environment);

			String pageInterceptorClassName = config.getPageInterceptorClassName();
			String pageDialectClassName = config.getPageDialectClassName();

			if (StringUtil.isNotNull(pageInterceptorClassName) && StringUtil.isNotNull(pageDialectClassName)) {
				// 加载方言分页插件到mybatis
				addPageInterceptor(configuration, pageInterceptorClassName, pageDialectClassName);
			}

			// 把所有的dao接口 加到Mybatis的configuration当中(根据注解判断)
			for (Class<?> daoClass : classList) {
				Annotation annotationInst = daoClass.getAnnotation(daoAnnotationClass);
				if (annotationInst != null) {
					configuration.addMapper(daoClass);
				}
			}

			// 创建SqlSessionFactory的Map
			SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(configuration);
			sqlSessionFactoryMap.put(annotationClassName, sqlSessionFactory);
		}

		// 每个数据源打开一个sqlSession 只是用于装配dao对象 最后会关上的~~
		for (Entry<String, SqlSessionFactory> entry : sqlSessionFactoryMap.entrySet()) {
			SqlSession sqlSession = entry.getValue().openSession();
			sqlSessionMap.put(entry.getKey(), sqlSession);
		}

	}

	/**
	 * 添加分页Interceptor
	 * 
	 * @param configuration
	 * @param pageInterceptorClassName
	 * @param pageDialectClassName
	 * @throws LoraCoreException
	 */
	private void addPageInterceptor(Configuration configuration, String pageInterceptorClassName, String pageDialectClassName)
			throws LoraCoreException {
		Dialect dialect = null;
		try {
			dialect = (Dialect) Class.forName(pageDialectClassName).newInstance();
		} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {

			ErrorContext ec = new ErrorContext();
			ec.className(pageDialectClassName).message("reflect creat Bean Fail");
			ExceptionPackageFactory.excute(e, ec);

		}

		if (dialect == null) {
			return;
		}

		Class<?> clz = null;
		try {
			clz = Class.forName(pageInterceptorClassName);
		} catch (ClassNotFoundException e) {
			ErrorContext ec = new ErrorContext();
			ec.className(pageInterceptorClassName).message("class cant find");
			ExceptionPackageFactory.excute(e, ec);
		}
		Constructor<?> constructor = null;
		try {
			if (clz != null) {
				constructor = clz.getConstructor(Dialect.class);
			}
		} catch (NoSuchMethodException | SecurityException e1) {
			ErrorContext ec = new ErrorContext();
			ec.className(pageInterceptorClassName).message("get Constructor fail").parameterTypeArray(new String[] { dialect.toString() });
			ExceptionPackageFactory.excute(e1, ec);
		}

		Interceptor interceptor = null;
		try {
			if (constructor != null) {
				interceptor = (Interceptor) constructor.newInstance(dialect);
			}
		} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e2) {
			ErrorContext ec = new ErrorContext();
			ec.className(pageInterceptorClassName).parameterTypeArray(new String[] { dialect.toString() })
					.message("Constructor Method Excute fail");
			ExceptionPackageFactory.excute(e2, ec);
		}

		configuration.addInterceptor(interceptor);
	}

	/**
	 * 获取MongoClient对象 并 装配MongoDAOImpl
	 */
	private void initMongoClient() {

		MongoDBConfig mongoDBConfig = configXmlEntity.getMongoDBConfig();

		if (mongoDBConfig == null) {
			return;
		}

		ServerAddress serverAddress = new ServerAddress(mongoDBConfig.getUrl(), mongoDBConfig.getPort());

		MongoClientOptions.Builder build = new MongoClientOptions.Builder();

		// 与目标数据库能够建立的最大connection数量为50
		build.connectionsPerHost(mongoDBConfig.getConnectionsPerHost());

		// 如果当前所有的connection都在使用中，则每个connection上可以有50个线程排队等待
		build.threadsAllowedToBlockForConnectionMultiplier(mongoDBConfig.getThreadsAllowedToBlockForConnectionMultiplier());
		/*
		 * 一个线程访问数据库的时候，在成功获取到一个可用数据库连接之前的最长等待时间为2分钟
		 * 这里比较危险，如果超过maxWaitTime都没有获取到这个连接的话，该线程就会抛出Exception
		 * 故这里设置的maxWaitTime应该足够大，以免由于排队线程过多造成的数据库访问失败
		 */
		build.maxWaitTime(mongoDBConfig.getMaxWaitTime());

		// 与数据库建立连接的timeout设置为1分钟
		build.connectTimeout(mongoDBConfig.getConnectTimeout());

		MongoClientOptions options = build.build();

		this.mongoClient = new MongoClient(serverAddress, options);
		this.mongoDAOImpl = new MongoDAOImpl(this.mongoClient);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.lora.core.scan.IScanClass#loadClassList(java.util.List)
	 */
	@Override
	public List<Class<?>> loadClassList(List<String> basePackageNameList) throws LoraCoreException {

		try {
			for (String packageDirName : basePackageNameList) {

				packageDirName = packageDirName.replace(StringUtil.POINT, StringUtil.SLASH);

				Enumeration<URL> dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
				while (dirs.hasMoreElements()) {
					URL url = dirs.nextElement();

					// 根据URL扫描class
					scanAllClassByUrl(url, packageDirName);
				}
			}
		} catch (Exception e) {
			throw new LoraCoreException(e);
		}

		return classList;
	}

	/**
	 * 根据URL扫描class
	 * 
	 * @param url
	 * @param packageDirName
	 * @throws ClassNotFoundException
	 * @throws IOException
	 * @throws LoraCoreException
	 */
	private void scanAllClassByUrl(URL url, String packageDirName) throws LoraCoreException {

		String protocol = url.getProtocol();

		if (PROTOCOL_FILE.equals(protocol)) {

			String fileUrl = url.getFile();
			File file = new File(fileUrl);

			scanFiles(file, classList);
		} else if (PROTOCOL_JAR.equals(protocol)) {

			JarFile jar = null;
			try {
				jar = ((JarURLConnection) url.openConnection()).getJarFile();
			} catch (IOException e) {
				ErrorContext ec = new ErrorContext();
				ec.url(url.toString()).message("url error");
				ExceptionPackageFactory.excute(e, ec);
			}

			if (jar != null) {

				// 列出所有的元素 包括所有的文件和文件夹 所以不需要进行循环遍历
				Enumeration<JarEntry> entries = jar.entries();
				while (entries.hasMoreElements()) {
					JarEntry entry = entries.nextElement();
					scanJarFile(entry, classList, packageDirName);
				}
			}

		}

	}

	/**
	 * 遍历jar文件内部的class文件 （去除了内部类，也就是说 内部类无法进行注入，也无法将内部类注入到其他类中）
	 * 
	 * @param entry
	 * @param classList
	 * @param packageDirName
	 * @throws LoraCoreException
	 */
	private void scanJarFile(JarEntry entry, List<Class<?>> classList, String packageDirName) throws LoraCoreException {

		if (entry.isDirectory()) {
			return;
		}

		String name = entry.getName();

		// 如果是以/开头的
		if (name.startsWith(StringUtil.SLASH)) {
			// 获取后面的字符串
			name = name.substring(1);
		}
		// 如果前半部分和定义的包名相同
		if (name.startsWith(packageDirName)) {
			int idx = name.lastIndexOf(StringUtil.SLASH);

			// 如果以"/"结尾 是一个包
			if (idx == -1) {
				scanClass(classList, name, idx);
			}
		}

	}

	/**
	 * 扫描类
	 * 
	 * @param classList
	 * @param name
	 * @param idx
	 * @throws LoraCoreException
	 */
	private void scanClass(List<Class<?>> classList, String name, int idx) throws LoraCoreException {
		// 获取包名 把"/"替换成"."
		String packageName = name.substring(0, idx).replace(StringUtil.SLASH, StringUtil.POINT);

		// 如果是一个.class文件 而且不是内部类
		if (name.endsWith(EXT) && name.indexOf('$') == -1) {
			// 去掉后面的".class" 获取真正的类名
			String fullClassName = packageName + StringUtil.POINT + name.substring(packageName.length() + 1, name.length() - 6);
			try {
				classList.add(Class.forName(fullClassName));
			} catch (ClassNotFoundException e) {
				ErrorContext ec = new ErrorContext();
				ec.className(fullClassName).message(ErrorContext.CANT_FIND_CLASS);
				ExceptionPackageFactory.excute(e, ec);
			}
		}
	}

	/**
	 * 文件扫描方法 循环迭代寻找所有的class文件
	 * 
	 * @param file
	 * @param classList
	 * @throws LoraCoreException
	 */
	private void scanFiles(File file, List<Class<?>> classList) throws LoraCoreException {
		if (file.isDirectory()) {

			for (File f : file.listFiles()) {
				if (f.isDirectory() || f.getName().endsWith(EXT)) {
					scanFiles(f, classList);
				}
			}

		} else {

			final String packagePath = file.getAbsolutePath().substring(file.getAbsolutePath().indexOf(CLASS_PATH) + CLASS_PATH.length());

			String classFullName = packagePath.replace(File.separator, StringUtil.POINT).replace(EXT, StringUtil.BLANK);

			Class<?> clazz = null;
			try {
				clazz = Class.forName(classFullName);
			} catch (ClassNotFoundException e) {
				ErrorContext ec = new ErrorContext();
				ec.className(classFullName).message("cant find class");
				ExceptionPackageFactory.excute(e, ec);
			}

			if (clazz != null) {
				classList.add(clazz);
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.lora.core.assemble.IAssembleClass#assembleObject(org.lora.core.configxml
	 * .entity.ConfigXmlEntity, java.util.List)
	 */
	@Override
	public List<Object> assembleObject() throws LoraCoreException {

		List<Object> actionObjectList = new ArrayList<>();

		try {

			// 加载所有需要扫描的Class
			loadClassList(configXmlEntity.getBasePackNameList());

			// 初始化数据库连接池
			initDataSource();

			// 初始化 和 MyBatis相关的配置
			initMyBatisDAO();

			// 获取MongoClient对象 并 装配MongoDAOImpl
			initMongoClient();

			for (Class<?> clz : classList) {
				// 装配Bean
				Object targetObject = creatBean(clz, true, null);

				if (targetObject != null) {
					actionObjectList.add(targetObject);
				}

			}

			// 装配webcontext的成员变量
			assmbleContext();
		} catch (ClassNotFoundException | LoraCoreException | IllegalAccessException | InstantiationException | NoSuchFieldException e) {
			throw new LoraCoreException(e.getMessage(), e);
		} finally {
			// 每个数据源打开一个sqlSession 只是用于装配dao对象 最后会关上的~~
			for (Entry<String, SqlSession> entry : sqlSessionMap.entrySet()) {
				entry.getValue().close();
			}
		}

		return actionObjectList;
	}

	/**
	 * 组装普通Bean
	 * 
	 * @param clz
	 * @param resource
	 * @return
	 * @throws ClassNotFoundException
	 * @throws LoraCoreException
	 * @throws IllegalAccessException
	 */
	private Object creatNormalBean(Class<?> clz, String resource) throws LoraCoreException {

		// 解决重复装配问题
		if (serviceBeanMap.containsKey(clz.getName())) {
			return serviceBeanMap.get(clz.getName());
		}

		Class<?> targetClass;
		Object targetObject = null;

		try {

			if (StringUtil.isNotNull(resource)) {
				// 直接根据参数获取Class
				targetClass = Class.forName(resource);
			} else {
				// 寻找实现类的class
				targetClass = getTargetClass(clz);
				// 2016-09-21 无法装配的时候不再抛错 而是忽略到这个 继续装配
				if (targetClass == null) {
					return null;
				}
			}

			// 创建代理类的实例
			targetObject = creatCglibProxyObject(targetClass, null);
			/*
			 * 这里root为false 从这个方法出去以后 root都为false。 所以这限制了只能在action里面注入service。
			 * 而不能在service里面注入action。
			 */
			Service serviceAnnotaion = targetClass.getAnnotation(Service.class);
			if (serviceAnnotaion != null) {
				// 注入成员变量
				List<Field> fieldList = ReflectUtil.getAllField(new ArrayList<Field>(), targetClass);
				for (Field field : fieldList) {
					creatField(targetObject, field);
				}
			}

			Service serviceAnnotation = targetClass.getAnnotation(Service.class);
			if (serviceAnnotation != null) {
				serviceBeanMap.put(clz.getName(), targetObject);
			}

		} catch (ClassNotFoundException | LoraCoreException e) {
			ErrorContext ec = new ErrorContext();
			ec.className(resource).message("cant find class");
			ExceptionPackageFactory.excute(e, ec);
		}

		return targetObject;
	}

	/**
	 * 迭代创建Bean对象,迭代注入成员变量
	 * 
	 * @param clz
	 * @param isRoot
	 *            为了第一次调用的时候 只遍历Action注解的class（这个设置有些狭隘，以后有很大可能会改掉）
	 * @param resource
	 * @return
	 * @throws LoraCoreException
	 */
	private Object creatBean(Class<?> clz, boolean isRoot, String resource) throws LoraCoreException {
		Action actionAnnotaion = clz.getAnnotation(Action.class);

		Object targetObject = null;

		if (isRoot) {
			if (actionAnnotaion != null) {
				// 获取实现类的class
				Class<?> targetClass = getTargetClass(clz);
				// 2016-09-21 无法装配的时候不再抛错 而是忽略到这个 继续装配
				if (targetClass == null) {
					return null;
				}

				// 创建代理类的实例
				targetObject = creatCglibProxyObject(targetClass, null);
				// 注入成员变量
				List<Field> fieldList = ReflectUtil.getAllField(new ArrayList<Field>(), targetClass);
				for (Field field : fieldList) {
					creatField(targetObject, field);
				}
			} else {
				return targetObject;
			}
		} else {

			// 判断这个类 是不是一个dao接口类
			SqlSession sqlSession = getSqlSession(clz);

			if (sqlSession != null) {// 说明这是一个DAO 用 sqlSession来装配他!
				targetObject = sqlSession.getMapper(clz);
			} else if (clz.isAssignableFrom(IMongoDAO.class)) {// 说明这是一个操作MongoDB的DAO
				targetObject = this.mongoDAOImpl;
			} else {// 普通类型 平常方法装配
				targetObject = creatNormalBean(clz, resource);
			}

		}

		return targetObject;
	}

	/**
	 * 获取这个DAO 对应的数据源的SqlSession
	 * 
	 * @param clz
	 * @return
	 */
	private SqlSession getSqlSession(Class<?> clz) {

		Annotation[] annotationArray = clz.getAnnotations();

		for (Annotation entry : annotationArray) {

			String annotationClassName = entry.annotationType().getName();

			if (annotationClassNameList.contains(annotationClassName)) {
				return sqlSessionMap.get(annotationClassName);
			}

		}

		return null;

	}

	/**
	 * 获取Cglib代理对象
	 * 
	 * @param superClass
	 * @param callback
	 * @return
	 */
	private Object creatCglibProxyObject(Class<?> superClass, Callback callback) {

		Enhancer enhancer = new Enhancer();
		if (callback == null) {
			enhancer.setCallback(new ProxyMethodInterceptor());
		} else {
			enhancer.setCallback(callback);
		}
		enhancer.setSuperclass(superClass);

		return enhancer.create();
	}

	/**
	 * 迭代创建成员变量
	 * 
	 * @param targetObject
	 * @param field
	 * @throws IllegalAccessException
	 * @throws LoraCoreException
	 * @throws ClassNotFoundException
	 */
	private void creatField(Object targetObject, Field field) throws LoraCoreException {

		AutoAssemble autoAssembleAnnotaion = field.getAnnotation(AutoAssemble.class);

		if (autoAssembleAnnotaion == null) {
			return;
		}

		String resource = autoAssembleAnnotaion.resource();

		try {

			Object fieldObject = creatBean(field.getType(), false, resource);
			field.setAccessible(true);
			field.set(targetObject, fieldObject);
		} catch (LoraCoreException | IllegalAccessException e) {
			ErrorContext ec = new ErrorContext();
			String fieldType = field.getType().getName();
			String fieldName = field.getName();
			String className = targetObject.getClass().getName();
			ec.fieldType(fieldType).fieldName(fieldName).className(className).message("field set error");
			ExceptionPackageFactory.excute(e, ec);
		}

	}

	/**
	 * 获取实现类的Class<br>
	 * <br>
	 * 根据targetClz 判断 如果targetClz本身是一个接口类，则在classList中寻找它的实现类<br>
	 * 如果targetClz 不是一个接口类，则直接返回targetClz<br>
	 * 
	 * @param targetClz
	 * @param classList
	 * @return
	 * @throws LoraCoreException
	 * @throws Exception
	 */
	private Class<?> getTargetClass(Class<?> targetClz) throws LoraCoreException {

		if (!targetClz.isInterface()) {// 不是一个接口类，则直接返回targetClz
			return targetClz;
		}

		Class<?> resultClz = null;

		// 先寻找目标Class的实现类
		for (Class<?> clz : classList) {
			if (clz.isInterface()) {
				continue;
			}

			if (targetClz.isAssignableFrom(clz) && !Modifier.isAbstract(clz.getModifiers())) {
				resultClz = clz;
				// TODO 此处缺乏一个接口多个实现的判断 需要以后修改
			}

		}

		if (resultClz == null) {
			// throw new LoraCoreException("Error005", targetClz +
			// " cant find impl class");
			// 2016-09-21 无法装配的时候不再抛错 而是忽略到这个 继续装配
			systemLog.error("Assignable Error [" + targetClz + "] cant find impl class !");
		}

		return resultClz;

	}

	/**
	 * 创建SecurityContext对象
	 * 
	 * @return
	 * @throws ClassNotFoundException
	 * @throws LoraCoreException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 */
	private SecurityContext assmbleSecurityContext() throws ClassNotFoundException, LoraCoreException, InstantiationException,
			IllegalAccessException {

		WebSecurityConfig config = this.configXmlEntity.getWebSecurityConfig();

		String className = config.getSecurityServiceImpl();
		ValidateUtil.isNull(className, "SecurityServiceImpl Class Name");

		Class<?> clz = Class.forName(className);

		if (!ISecurityService.class.isAssignableFrom(clz)) {
			throw new LoraCoreException("Error006", "SecurityServiceImpl Class Name is not AssignableFrom ISecurityService");
		}

		SecurityContext context = new SecurityContext();

		ISecurityService service = (ISecurityService) creatNormalBean(clz, null);

		context.setService(service);

		return context;
	}

	/**
	 * 装配WebContext
	 * 
	 * @throws ClassNotFoundException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws LoraCoreException
	 */
	private void assmbleContext() throws ClassNotFoundException, InstantiationException, IllegalAccessException, LoraCoreException {
		SecurityContext securityContext = assmbleSecurityContext();

		WebContext webContext = WebContext.getInstance();

		webContext.setSecurityContext(securityContext);
		webContext.setServiceBeanMap(serviceBeanMap);
		webContext.setSqlSessionFactoryMap(sqlSessionFactoryMap);
		webContext.setDataSourceMap(dataSourceMap);
	}

}
